import ExtractBloomStage from './ExtractBloomStage'
import BlurStage2 from './BlurStage2'
import { Pass } from './Pass'

class GlowStage extends Pass {
  constructor (scene) {
    super(scene)
    this.scene = scene
    this.intensity = 0.5
    this.name = 'czm_glow'
  }

  createStage () {
    const scene = this.scene
    const width = scene.drawingBufferWidth
    const height = scene.drawingBufferHeight

    const nMips = 5
    const kernelSizeArray = [10, 20, 30, 40, 50]
    let resx = Math.round(width / 2)
    let resy = Math.round(height / 2)
    const blurStates = []

    const extractBloomPass = new ExtractBloomStage(scene)
    extractBloomPass.createStage()
    blurStates.push(extractBloomPass.stage)

    let inputFrameTexture = extractBloomPass.name

    for (let i = 0; i < nMips; i++) {
      const texSize = new GC.Cartesian2(resx, resy)
      resx = Math.round(resx / 2)
      resy = Math.round(resy / 2)
      const blurX = new BlurStage2({
        scene,
        texSize,
        direction: new GC.Cartesian2(1, 0),
        colorTexture: inputFrameTexture,
        kernelRadius: kernelSizeArray[i]
      })
      const blurY = new BlurStage2({
        scene,
        texSize,
        direction: new GC.Cartesian2(0, 1),
        colorTexture: blurX.name,
        kernelRadius: kernelSizeArray[i]
      })

      blurStates.push(blurX.stage, blurY.stage)
      inputFrameTexture = blurY.name
    }

    const glowBlurBuild = new GC.PostProcessStageComposite({
      name: 'czm_glowBlurBuild',
      stages: blurStates
    })

    const bloomTintColors = [
      new GC.Cartesian3(1, 1, 1),
      new GC.Cartesian3(1, 1, 1),
      new GC.Cartesian3(1, 1, 1),
      new GC.Cartesian3(1, 1, 1),
      new GC.Cartesian3(1, 1, 1)
    ]
    const bloomFactors = [1.0, 0.8, 0.6, 0.4, 0.2]

    const bloomComposite = new GC.PostProcessStage({
      name: 'czm_bloom_composite_lxg',
      fragmentShader: this.getCompositeShader(nMips),
      uniforms: {
        blurTexture1: blurStates[0].name,
        blurTexture2: blurStates[1].name,
        blurTexture3: blurStates[2].name,
        blurTexture4: blurStates[3].name,
        blurTexture5: blurStates[4].name,
        bloomStrength: this.intensity,
        bloomRadius: 0.5,
        bloomFactors,
        bloomTintColors
      }
    })

    this.stage = new GC.PostProcessStageComposite({
      name: 'czm_bloom_final',
      stages: [glowBlurBuild, bloomComposite],
      inputPreviousStageTexture: false,
      uniforms: {}
    })
    // this.stage = extractBloomPass.stage
  }

  getCompositeShader (nMips) {
    return `
      #define NUM_MIPS ${nMips}
      in vec2 v_textureCoordinates;
      uniform sampler2D blurTexture1;
      uniform sampler2D blurTexture2;
      uniform sampler2D blurTexture3;
      uniform sampler2D blurTexture4;
      uniform sampler2D blurTexture5;
      uniform sampler2D dirtTexture;
      uniform sampler2D colorTexture;
      uniform float bloomStrength;
      uniform float bloomRadius;
      uniform float bloomFactors[NUM_MIPS];
      uniform vec3 bloomTintColors[NUM_MIPS];
      float lerpBloomFactor(const in float factor) {
        float mirrorFactor = 1.2 - factor;
        return mix(factor, mirrorFactor, bloomRadius);
      }
      void main() {
        vec4 color = bloomStrength * ( lerpBloomFactor(bloomFactors[0]) * vec4(bloomTintColors[0], 1.0) * texture(blurTexture1, v_textureCoordinates) +
          lerpBloomFactor(bloomFactors[1]) * vec4(bloomTintColors[1], 1.0) * texture(blurTexture2, v_textureCoordinates) +
          lerpBloomFactor(bloomFactors[2]) * vec4(bloomTintColors[2], 1.0) * texture(blurTexture3, v_textureCoordinates) +
          lerpBloomFactor(bloomFactors[3]) * vec4(bloomTintColors[3], 1.0) * texture(blurTexture4, v_textureCoordinates) +
          lerpBloomFactor(bloomFactors[4]) * vec4(bloomTintColors[4], 1.0) * texture(blurTexture5, v_textureCoordinates) );
        out_FragColor = color + texture(colorTexture, v_textureCoordinates);
      }
    `
  }
}

export default GlowStage
